var Gallery = new Class({

	Implements: Options,

	options: {
		// blok przechowywujacy grafiki dla danej galerii
		'imageList':'',
		// blok glownej grafiki po wczytaniu
		'imageMain':'',
		'imageDescription':'',
		'categoryList':'',
		'galleryList':'',
		// nawigacja
		'imageNext':'',
		'imagePrev':'',
		'periodical':3000,
		'imagePlay':'',
		'urlSmallPath': '',
		'urlMediumPath': '',
		// loader
		'loading':'',
		'thumb': {
			'small': {'width':50,'height':50, 'auto':false},
			'medium': {'width':500,'height':500,'auto': true}
		},
		'url': {
			'getAllCategories':'?getAllCategories',
			'getGalleriesForCategory':'?getGalleriesForCategory={id}',
			'getImagesForGallery':'?getImagesForGallery={id}',
		}
	},

	initialize: function(options) {
		
		this.setOptions(options);

		// inicjowanie innych opcji
		this.setUrlSmallPath(this.options.urlSmallPath);
		this.setUrlMediumPath(this.options.urlMediumPath);

		// przechowuje informacje o kategoriach
		this.category = new Hash();
		// przechowuje informacje o galeriach
		this.gallery = new Hash();
		// przechowuje informacje o obrazach
		this.image = new Hash();
		// przechowuje informacje o zalaznosci jaka kategoria ma jaka galerie
		this.galleryInCategory = new Hash();
		
		// nie wcisniety przycisk prezentacji
		this.isPlayPressed = false;
		this.handlePlayPeriodical = $empty;
		
		this.initControls();

		this.load();
		this.renderCategories();
	},

	initControls: function() {
		var self = this;
		this.options.imageNext.addEvent('click', function(e){ e.stop(); self.handleNext(); });
		this.options.imagePrev.addEvent('click', function(e){ e.stop(); self.handlePrev(); });
		this.options.imagePlay.addEvent('click', function(e){ e.stop(); self.handlePlay(); });
	}, 

	renderCategories: function() {
		var self = this;

		// wyczyszczenie elementu
		this.options.categoryList.empty();

		var el = new Element('ul',{});

		this.category.each(function(item){
			el.adopt(new Element('li',{
				'id':'category-' + item.id
			}).grab(new Element('a',{
				'text':item.name,
				'events': {
					'click': function(e){
						// stop event
						e.stop();
						// ustawienie aktualnej kategorii
						self.currentCategory = item;
						// zaladowanie galerii dla kategorii
						self.renderGalleryForCategory(item.id);
					}
				}
			})));
		});

		this.options.categoryList.grab(el);

		// ustawienie pierwszej galerii jako aktywną
		// dla pierwszej kategorii
		if ($chk(this.currentCategory)) {
			this.renderGalleryForCategory(this.currentCategory.id);
		}
	},

	renderGalleryForCategory: function(category) {
		var self = this;

		// wyczyszczenie elementu
		this.options.galleryList.empty();

		var el = new Element('ul',{});

		var galleries = this.getGalleries(category);
		galleries.each(function(item,k){
			el.adopt(new Element('li',{
				'id':'gallery-' + item.id
			}).adopt(
				new Element('h6',{}).grab(new Element('a',{
					'text':item.name,
					'events': {
						'click': function(e){
							// stop event
							e.stop();
							// ustawienie aktualnej galerii
							self.currentGallery = item;
							// zaladowanie grafik dla galerii
							self.renderImagelistForGallery(item.id);
						}
					}
				}))
			));
		});

		this.options.galleryList.grab(el);

		// zaladowanie grafik
		// dla pierwszej galerii
		if ($chk(this.currentGallery)) {
			this.renderImagelistForGallery(this.currentGallery.id);
		}

		// tworzenie zaznaczenia
		this.makeSelected($('category-' + category));
	},

	// FIXED: Probelem jest taki że tablica z images jest prawdopodobnie pusta!!
	// wszystko przez AJAX - rozwiazane {async:false}

	renderImagelistForGallery: function(gallery) {
		var self = this;
		
		// wyczyszczenie elementu
		self.options.imageList.empty();
		// efekt myslenia on :P
		this.initLoadingEffect(self.options.imageList);

		// ustawienie aktualnej grafiki na null
		// nizej zostanie ustawiona aktualna grafika ;]
		this.currentImage = null;

		// pobranie grafik dla galerii
		var images = this.image.get(gallery);
		if ($chk(images)) {
			// istnieja
			var el = new Element('ul',{});
			images.each(function(item){
				if (null === self.currentImage && $chk(self.getImages(gallery)[0])) {
					self.currentImage = self.getImages(gallery)[0];
				};

				el.grab(new Element('li',{
					'id':'image-' + item.id
				}).grab(
					new Element('a',{'events':{
						'click': function(){ return false; }
					}}).grab(new Element('div',{
							'style': 'background-image:url(' + self.getUrlSmallPath(item.image) + ')',
							'events': {
								'click': function(e){
									// stop event
									e.stop();
									// ustawienie aktualnej galerii
									self.currentImage = item;
									// zaladowanie sredniej wielkości grafiki
									self.loadMediumImage(item);
								}
							}
					}))
				));
			});
		} else {
			// nie istnieja
			var el = new Element('p',{'text':'Nie ma zdięć w galerii'});
		}

		this.options.imageList.grab(el).grab(new Element('div',{'class':'clear'}));

		// ustawienie pierwszej grafiki na medium
		if ($chk(this.currentImage)) {
			this.loadMediumImage(this.currentImage);
		}
		
		// tworzenie zaznaczenia
		this.makeSelected($('gallery-' + gallery));
	},

	// efekt wczytywania do bloku
	initLoadingEffect: function(el) {
		var effect = new Fx.Morph(el, {
			duration: 500,
			transition: Fx.Transitions.Bounce.easeIn
		});
	},

	loadMediumImage: function(item){
		var self = this;

		this.requestStart();

		var src = self.getUrlMediumPath(item.image);

		var myImages = new Asset.images([src], {
			onProgress: this.requestStart,
		    onComplete: function(){
		       self.options.imageMain.set('src', src);
		       self.requestEnd();
		    }
		});
		
		// tworzenie zaznaczenia
		this.makeSelected($('image-'+item.id));
	},

	makeSelected: function(element) {
		if ($chk(element)) {
			// kolekcja elementow przed i po
			// posiadajacych klase `selected`
			var colection = [];
			var prev = element.getPrevious('.selected');
			var next = element.getNext('.selected');
			// laczenie w/w i znalezionych elementow
			if ($chk(prev)) colection.include(prev);
			if ($chk(next)) colection.include(next);
			// usuwanie z nich klasy `selected`
			colection.each(function(el){ el.removeClass('selected'); });
			// dodanie do elementu aktywnego klasy `selected`
			element.addClass('selected');
		}
	},

	requestStart: function(){
		$('loading').setStyle('display','inline');
	},
	
	requestEnd: function(){
		$('loading').setStyle('display','none');
	},

	// inicjuje wszystko
	load: function() {
		var self = this;

		// wczytujemy kategorie
		var categories = this.loadCategories();
		categories.each(function(item){
			var categoryID = item.id;
			// jeżeli nie ma ustawionej domyslnej galerii
			// to ustaw pierwszy rekord
			if (!$chk(self.currentCategory)) {
				self.currentCategory = item;
			}

			// dodajemy kategorie i galerie jakie moga byc
			self.setCategory(item.id, item);

			// wczytujemy galerie
			var galleries = self.loadGalleryForCategory(item.id);
			galleries.each(function(item){
				// jeżeli nie ma ustawionej domyslnej galerii
				// to ustaw pierwszy rekord
				if (!$chk(self.currentGallery)) {
					self.currentGallery = item;
				}

				var galleryID = item.id;
				// dodaj galerie jezeli tylko nie istnieje w kategorii
				if(!self.hasGallery(galleryID)){

					self.setGallery(galleryID, item);
					self.setGalleryForCategory(galleryID, categoryID);

					// wczytuje grafiki dla galerii
					self.loadImagesForGallery(galleryID);

					// jeżeli nie ma ustawionej domyslnej grafiki
					// to ustaw pierwszy rekord
					if (!$chk(self.currentImage) && $chk(self.getImages(galleryID)[0])) {
						self.currentImage = self.getImages(galleryID)[0];
					};
				}
			});
		});
	},

	// wczytuje via AJAX kategorie
	loadCategories: function(){
		var self = this;
		var result = [];
		var jsonRequest = new Request.JSON({
			url: this.options.url.getAllCategories,
			async: false,
			onRequest: this.requestStart,
			onComplete: function(categories){
		    	result = categories;
		    	self.requestEnd();
			}
		}).get();
		
		return result;
	},

	// wczytuje via AJAX galerie dla kategorii
	loadGalleryForCategory: function(id) {
		var self = this;
		var result = [];

		var jsonRequest = new Request.JSON({
			url: this.options.url.getGalleriesForCategory.replace('{id}',id),
			async: false,
			onRequest: this.requestStart,
			onComplete: function(galleries){
		    	result = galleries;
		    	self.requestEnd();
			}
		}).get();
		
		return result;
	},

	// wczytuje via AJAX zdiecia dla galerii
	loadImagesForGallery: function(id) {
		var self = this;
		var request = new Request.JSON({
			url: this.options.url.getImagesForGallery.replace('{id}',id),
			async: false,
			onComplete: function(images){
				self.setImages(images, id);
			}
		}).get();
	},

	// dodaje kategorie
	setCategory: function(name, data) {
		this.category.set(name, data);
	},

	// TODO: dodaje kilka kategorii
	addCategories: function(categories) {
	},
	
	hasGallery: function(name) {
		return this.gallery.has(name);
	},
	
	// dodaje galerie
	setGallery: function(name, data) {
		this.gallery.set(name, data);
	},
	// zwraca galerie o podanym id
	getGallery: function(name) {
		return this.gallery.get(name);
	},

	setGalleryForCategory: function(gallery, category) {
		var g = this.galleryInCategory.has(category)
					? this.galleryInCategory.get(category)	: new Array();
		g.push(gallery);
		this.galleryInCategory.set(category, g);
	},
	getGalleries: function(category){
		var self = this;
		var result = new Array();
		this.galleryInCategory.get(category).each(function(item,e){
			result.push(self.getGallery(item));
		});
		return result;
	},

	// TODO: dodaje kilka galerii
	addGalleries: function(galleries, categories) {},

	// dodaje obrazy do galeri
	setImages: function(images, gallery){
		this.image.set(gallery,images)
	},
	// zwraca grafiki do nazwy gallery
	getImages: function(gallery) {
		return this.image.get(gallery);
	},

	setUrlSmallPath: function(path) {
		this.urlSmallPath = path;
	},

	getUrlSmallPath: function(image) {
		return this.urlSmallPath + '/' + image;
	},

	setUrlMediumPath: function(path) {
		this.urlMediumPath = path;
	},

	getUrlMediumPath: function(image) {
		return this.urlMediumPath + '/' + image;
	},

	currentCategory: null,
	currentGallery: null,

	currentImage: null,

	nextImage: function() {
		// sprawdz czy jest juz aktywna galeria lub jest zaznaczona grafika
		if (!$chk(this.currentGallery) || !$chk(this.currentImage)) {
			return false;
		}
		// pobranie tablicy grafik
		var images = this.getImages(this.currentGallery.id);
		// odnalezienie aktywnej grafiki
		var index = images.indexOf(this.currentImage);
		// zwrocenie nastepnego obiektu grafiki
		return this.currentImage = images.length <= index+1 ? images[0] : images[index+1];
	},
	prevImage: function() {
		// sprawdz czy jest juz aktywna galeria lub jest zaznaczona grafika
		if (!$chk(this.currentGallery) || !$chk(this.currentImage)) {
			return false;
		}
		// pobranie tablicy grafik
		var images = this.getImages(this.currentGallery.id);
		// odnalezienie aktywnej grafiki
		var index = images.indexOf(this.currentImage);
		// zwrocenie poprzedniego obiektu grafiki
		return this.currentImage = index-1 < 0 ? images[images.length] : images[index-1];
	},
	
	handleNext: function(instance){
		var self = $chk(instance) ? instance : this;
		var next = self.nextImage();
		if ($chk(next)) {
			self.loadMediumImage(next);
		}
	},
	handlePrev: function(e){
		var prev = this.prevImage();
		if ($chk(prev)) {
			this.loadMediumImage(prev);
		}
	},
	handlePlay: function(){
		// uruchomienie bądz zatrzymanie otwarzacza
		if (this.isPlayPressed !== true) {
			this.isPlayPressed = true;
			this.handlePlayPeriodical = this.handleNext.periodical(this.options.periodical,{}, this);
			this.options.imagePlay.addClass('play').removeClass('stop');
		} else {
			this.isPlayPressed = false;
			// TODO: jest problem z wyczyszczeniem interwalu
			$clear(this.handlePlayPeriodical);
			this.options.imagePlay.addClass('stop').removeClass('play');
		}
	},
});